package com.om.switchtopolymorphism;

public class RateCalculator {
	double calculateRate(Customer customer) {
		switch(customer.type) {
			case consumer:
				return calculateConsumerRate(customer);
			case business:
				return calculateBusinessRate(customer);
			case industrial:
				return calculateIndustrialRate(customer);
			default:
				return 0;
		}
	}

	double calculateConsumerRate(Customer customer) {
		if(customerIsEligibleForLifelineRate(customer)) {
			return calculateLifelineRate(customer);
		}

		return calculateTerritorialRate(customer);
	}

	boolean customerIsEligibleForLifelineRate(Customer customer) {
		return customer.rate == RateType.lifeline && customer.kwh <= 200;
	}

	double calculateLifelineRate(Customer customer) {
		int tier2Kwh = Math.max(customer.kwh - 100, 0);
		int tier1Kwh = customer.kwh - tier2Kwh;
		return tier1Kwh *0.03 + tier2Kwh * 0.05;
	}

	double calculateTerritorialRate(Customer customer) {
		switch(calculateTerritory(customer.address)) {
			case 1:
				// spec says territory 1 and 2 use same rate.
			case 2:
				return customer.kwh *(isWinter() ? .07 : .06);
			case 3:
				return customer.kwh *.065;
		}
	}

	int calculateTerritory(int address) {
		return address;
	}

	boolean isWinter() {
		return false;
	}

	double calculateBusinessRate(Customer customer) {
		double rate = 0;

		for(Site site : customer.sites) {
			rate += calculateSlidingScale(site.kwh);
		}

		return rate;
	}

	int calculateSlidingScale(int kwh) {
		return kwh;
	}

	double calculateIndustrialRate(Customer customer) {
		double businessRate = calculateBusinessRate(customer);
		double industrialRateModifier = calculateIndustrialRateModifier(customer);
		return businessRate *industrialRateModifier;
	}

	double calculateIndustrialRateModifier(Customer customer) {
		switch(customer.industrialRate) {
			case interruptable:
				return .8;
			case oneHourNotice:
				return .9;
			default:
				return .95;
		}
	}

}
